package com.lwp.test.aoptest.config;

import com.alibaba.fastjson.JSON;
import com.lwp.test.utils.ThreadUtils;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.Signature;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.context.annotation.EnableAspectJAutoProxy;
import org.springframework.core.Ordered;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;

@Component
// 同xml填写 <aop:aspectj-autoproxy/> 配置一个即可，两个一起也不冲突
@EnableAspectJAutoProxy
@Aspect
@Order(Ordered.LOWEST_PRECEDENCE - 1) // 方法中无效
public class AopConfig1 {

    private Logger logger = LoggerFactory.getLogger(this.getClass());

    private static final String EXECUTION = "execution(* com.lwp.test.aoptest.service..*.*(..))";

    @Pointcut("execution(* com.lwp.test.aoptest.service..*.*(..))")
    public void servicePointcut1() {
    }

    @Pointcut("execution(* com.lwp.test..*.service..*.*(..))")
    public void servicePointcut2() {
    }

    /**
     * @Pointcut("execution(* com.lwp.test.aoptest.service..*.*(..)) || execution(* com.lwp.test.*..*.service..*.*(..))")
     */
    @Pointcut("execution(* com.lwp.test.aoptest.service..*.*(..)) || execution(* com.lwp.test.*..*.service..*.*(..))")
    public void servicePointcut3() {
    }

    // 直接获取
    /*@Around(EXECUTION)
    public Object serviceAround1(ProceedingJoinPoint pjp) throws Throwable {
        // 获取参数
        Object[] args = pjp.getArgs();
        MethodSignature methodSignature = (MethodSignature) pjp.getSignature();
        long start = System.currentTimeMillis();
        logger.info("请求参数： {}", args);
        Object proceed = pjp.proceed(args);
        logger.info("响应： {}", proceed);
        logger.info("方法 {} 耗时： {}ms", methodSignature.getName(), System.currentTimeMillis() - start);
        return proceed;
    }*/

    /**
     * 多条件
     * <p>
     *     方式1： @Around("servicePointcut() || servicePointcut2()")
     *     方式2： @Around("execution(* com.lwp.test.aoptest.service..*.*(..)) || execution(* com.lwp.test.*..*.service..*.*(..))")
     *      execution(* com.lwp.test.*..*.service..*.*(..)) 切 com.lwp.test.任意包名 下或者子包中的 service包下的当前类和子孙包下的所有方法
     *      execution(* com.lwp.test..*.service..*.*(..)) 切 com.lwp.test 包下或者子包中的 service包下的当前类和子孙包下的所有方法
     * </p>
     * @param pjp
     * @return
     * @throws Throwable
     */
//    @Around("servicePointcut() || servicePointcut2()")
    @Around("servicePointcut3()")
//    @Around("execution(* com.lwp.test.aoptest.service..*.*(..)) || execution(* com.lwp.test.*..*.service..*.*(..))")
    public Object serviceAround(ProceedingJoinPoint pjp) throws Throwable {
        // 获取参数
        Object[] args = pjp.getArgs();
        MethodSignature methodSignature = (MethodSignature) pjp.getSignature();
        long start = System.currentTimeMillis();
        logger.info("请求参数： {}", args);
        Object proceed = pjp.proceed(args);
        logger.info("响应： {}", proceed);
        logger.info("方法 {} 耗时： {}ms", methodSignature.getName(), System.currentTimeMillis() - start);

        // 方法中线程变量
        System.out.println(JSON.toJSONString(ThreadUtils.EVENT_THREAD_LOCAL.get()));
        return proceed;
    }

/*    @Around("servicePointcut()")
    public Object serviceAround1(ProceedingJoinPoint pjp) throws Throwable {
        // 获取参数
        Object[] args = pjp.getArgs();
        MethodSignature methodSignature = (MethodSignature) pjp.getSignature();
        long start = System.currentTimeMillis();
        logger.info("AopConfig1 请求参数： {}", args);
        Object proceed = pjp.proceed(args);
        logger.info("AopConfig1 响应： {}", proceed);
        logger.info("AopConfig1 方法 {} 耗时： {}ms", methodSignature.getName(), System.currentTimeMillis() - start);
        return proceed;
    }*/
}
